package org.bigjava.novelplatform.common.formatters;

import lombok.extern.slf4j.Slf4j;
import org.bigjava.novelplatform.common.enums.CodeMesEnum;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * 类型转换器工厂，
 * 提供将code/枚举名转换为CodeMesEnum枚举的转换器
 * @author ykh
 * @create 2022-04-02 17:51
 */
@Slf4j
public class ToCodeMesEnum implements ConverterFactory<String, CodeMesEnum> {

    @Override
    public <T extends CodeMesEnum> Converter<String, T> getConverter(Class<T> targetType) {
        //公共属性
        Map<String, T> enumMap = new HashMap<>();
        Field[] fields = targetType.getFields();
        Method getCodeMethod = null;
        Method getNameMethod = null;

        try {
            getCodeMethod = targetType.getMethod("getCode");
            getNameMethod = targetType.getMethod("name");
        } catch (NoSuchMethodException e) {
            log.error("无法找到getCode或name方法", e);
            return source -> null; // 返回一个空的转换器
        }
        for (Field field : fields) {
            //目标类型
            if (field.getType().equals(targetType)) {
                try {
                    @SuppressWarnings("unchecked")
                    T enumInstance = (T) field.get(null); // 获取静态字段的值
                    String code = ((Integer) getCodeMethod.invoke(enumInstance)).toString();
                    String name = (String) getNameMethod.invoke(enumInstance);

                    enumMap.put(code, enumInstance);
                    enumMap.put(name.toLowerCase(), enumInstance);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    log.error("无法访问字段: {}", field.getName(), e);
                }
            }
        }
        if (enumMap.isEmpty()) {
            log.warn("警告：枚举{}未提供实例", targetType.getSimpleName());
        }

        return new ToEnumsConverter<>(enumMap);
    }

    /**
     * 类型转换器内部类，私有不允许访问和继承
     * @param <T> CodeMesEnum的实现
     */
    private static final class ToEnumsConverter<T extends CodeMesEnum> implements Converter<String, T> {

        private final Map<String, T> enumMap;

        public ToEnumsConverter(Map<String, T> enumMap) {
            this.enumMap = enumMap;
        }

        @Override
        public T convert(String source) {
            T result = enumMap.get(source.toLowerCase());
            if (result == null) {
                log.warn("警告：无法将参数{}映射到枚举{}的实例", source, enumMap.values().iterator().next().getClass().getSimpleName());
            }
            return result;
        }
    }


}
